package edu.washington.ling.syntric.consistency;

import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.struct.tree.Tree;

public class SupportVerbRule extends ConsistencyRule{
	@Override
	public void apply(Tree ds) {
		Token dsRoot = ds.getDSRoot();
		apply(dsRoot, ds);
	}

	private boolean isTransitive(Token verb) {
		boolean isTransitive = true;
		if (verb.hasFeature("unaccusative") || verb.hasFeature("passive")) {
			isTransitive = false;
		}
		return isTransitive;
	}
	private Token getPofArgChild(Token t) {
		Token pofArgChild = null;
		for (Token child: t.getDSDependents()) {
			if(child.getDSRelation().equals("r6-k1") || child.getDSRelation().equals("r6-k2")) {
				pofArgChild = child;
			}
		}
		return pofArgChild;
	}
	private void applyNominalType1(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test for type 1
		if (k1Child != null && k2Child == null && isTransitive(verb)) {
			int index = ds.nextCoindex();
			Token ec = ConsistencyUtils.createMovementEC("CASE", "pof", index);
			verb.addECDependent(ec);
			pofChild.setDSRelation("k2");
			pofChild.setDSTargetIndex(index);
			Token pofArgChild = getPofArgChild(pofChild);
			if (pofArgChild != null) {
				pofArgChild.setDSRelation("arg");
			}
		}
	}
	private void applyNominalType2(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test for type 2
		if (k1Child != null && k2Child != null && isTransitive(verb)) {
			int index = ds.nextCoindex();
			Token ec = ConsistencyUtils.createMovementEC("CASE", "arg", index);
			pofChild.addECDependent(ec);
			k2Child.setDSTargetIndex(index);
		}
	}
	private void applyNominalType3(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test for type 3
		if (k1Child == null && k2Child != null && !isTransitive(verb)) {
			int index = ds.nextCoindex();
			Token ec = ConsistencyUtils.createMovementEC("CASE", "pof", index);
			verb.addECDependent(ec);
			k2Child.setDSTargetIndex(index);
			pofChild.setDSRelation("k1");
			Token pofArgChild = getPofArgChild(pofChild);
			if (pofArgChild != null) {
				pofArgChild.setDSRelation("arg");
			}
		}
	}
	private void applyNominalType4(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test for type 4
		if (k1Child != null && k2Child != null && !isTransitive(verb)) {
			int index = ds.nextCoindex();
			Token ec = ConsistencyUtils.createMovementEC("CASE", "arg", index);				
			pofChild.addECDependent(ec);
			k2Child.setDSTargetIndex(index);
		}
	}
	private void applyNominal(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test
		if (pofChild.getTag().equals("NN") || pofChild.getTag().equals("NNP")) {
			// Response
			applyNominalType1(verb, pofChild, k1Child, k2Child, ds);
			applyNominalType2(verb, pofChild, k1Child, k2Child, ds);
			applyNominalType3(verb, pofChild, k1Child, k2Child, ds);
			applyNominalType4(verb, pofChild, k1Child, k2Child, ds);
		}
	}
	
	private void applyAdjectival(Token verb, Token pofChild, Token k1Child, Token k2Child, Tree ds) {
		// Diagnostic test (pt 1)
		if (pofChild.getTag().equals("JJ")) {
			// Diagnostic test (pt 2) 
			if (k1Child != null && k2Child == null && !verb.hasFeature("unaccusative")) {
				// Response
				int index = ds.nextCoindex();
				Token ec = ConsistencyUtils.createMovementEC("CASE", "k2", index);
				verb.addECDependent(ec);
				k1Child.setDSTargetIndex(index);
			}
		}
	}
	public void apply(Token t, Tree ds) {

		Token k1Child = null, k2Child = null, pofChild = null;
		for (Token child: t.getDSDependents()) {
			if (child.getDSRelation().equals("k1")) {
				k1Child = child;
			}
			if (child.getDSRelation().equals("k2")) {
				k2Child = child;
			}
			if (child.getDSRelation().equals("pof")) {
				pofChild = child;
			}
		}
		for (Token child: t.getECDependents()) {
			if (child.getDSRelation().equals("k1")) {
				k1Child = child;
			}
			if (child.getDSRelation().equals("k2")) {
				k2Child = child;
			}
		}
		// Diagnostic test
		if (pofChild != null && t.getTag().equals("VM")) {
			// Response
			applyNominal(t, pofChild, k1Child, k2Child, ds);
			applyAdjectival(t, pofChild, k1Child, k2Child, ds);
		}
	}
}
